---
title: 'Databases'
sidebarTitle: 'Databases'
description: 'Reference for connecting databases to Sequin'
---

 ## Supported databases

Sequin works with any PostgreSQL database version 14 or higher that supports [Logical Replication](https://www.postgresql.org/docs/current/logical-replication.html).

<Note>
  Sequin soft-supports PostgresSQL 12 and 13 with [some limitations](/reference/databases#postgresql-12-and-13).
</Note>

You can find guides for connecting to local and hosted databases in the [connect postgres](/connect-postgres) guide.

## Database connection details

Sequin requires the following details to connect to your database:

- **Host**: The hostname of your database
- **Port**: The port number of your database
- **Database**: The name of your database
- **Username**: The username of a database user with the [necessary permissions](#database-user-permissions)
- **Password**: The password for the database user

You can also enable or disable SSL mode for your database connection.

### Tunneling to your database

For development, you can connect Sequin to a database running on your local machine.

If your database is hosted by a cloud provider and requires a VPN to connect, Sequin can create a secure tunnel through a bastion host. Please [contact support](mailto:support@sequinstream.com) to enable this.

## Database user permissions

We recommend creating a dedicated database user for Sequin. Grant that user the following permissions:

- `connect` permission on the database.
- `select` permission on all the tables or schemas you want to connect to Sequin.
- `replication` permission (to read from replication slots).

You can create a user with those permissions with the following commands:

```sql
-- Create user with a secure password
create user sequin_user with password 'REPLACE_WITH_SECURE_PASSWORD';
-- Grant connect permission
grant connect on database your_database to sequin_user;
-- Grant select permission on tables you want to replicate
grant select on table table1, table2, table3 to sequin_user;
-- OR grant select on all tables in a schema
grant select on all tables in schema public to sequin_user;
-- Grant replication permission
alter user sequin_user with replication;
```

Please create a strong password for Sequin's database user. You can generate a secure password using the following command:

```bash
openssl rand -base64 24
```

## Enabling logical replication

Sequin requires logical replication to be enabled on your database. You can check if it's enabled:

```sql
show wal_level;
```

If the value isn't `logical`, you'll need to enable it. The process for enabling logical replication varies by provider. You can find more information in the following guides:

- [Standard PostgreSQL](/connect-postgres): Modify `postgresql.conf` to set `wal_level = logical`
- [AWS RDS](/how-to/setup-rds): Create a parameter group with `rds.logical_replication = 1`
- [Google Cloud SQL](/how-to/setup-gcp): Enable through the console or API
- [Azure](/how-to/setup-azure): Configure through server parameters
- [Neon](/how-to/setup-neon): Enable through project settings
- [Supabase](/how-to/setup-supabase): Enabled by default

<Warning>
Enabling logical replication often requires a database restart.
</Warning>

## Publications

[Publications](https://www.postgresql.org/docs/current/sql-createpublication.html) identify which tables to track for changes.

<Warning>
Create the [publication](#publications) **before** creating the replication slot. If you don't, the publication and slot combination may be invalid, and Sequin will fail to connect to your database.
</Warning>

### Creating a publication

The simplest publication includes all tables:

```sql
create publication sequin_publication for all tables;
```

To specify a subset of tables, use the following command:

```sql
create publication sequin_publication for table table1, table2, table3;
```

Or all tables in a schema:

```sql
create publication sequin_publication for tables in schema public;
```

### Working with partitioned tables

When using partitioned tables, you **must ensure [`publish_via_partition_root`](https://www.postgresql.org/docs/current/sql-createpublication.html#SQL-CREATEPUBLICATION-PARAMS-WITH-PUBLISH-VIA-PARTITION-ROOT) is set to `true`** to ensure Sequin captures changes correctly. This means changes to partition tables are associated with the root table:

```sql
-- Create publication for a partitioned table
create publication sequin_publication for table orders
with (publish_via_partition_root = true);

-- Or modify an existing publication
alter publication sequin_publication set (publish_via_partition_root = true);
```

<Note>
You can check this setting by running, for example:

```sql
SELECT pubviaroot FROM pg_publication where pubname = 'sequin_pub';
```

</Note>

### Modifying Publications

To add or remove tables from a publication, use the `ALTER PUBLICATION` statement:

```sql
-- To remove specific tables
alter publication sequin_publication drop table table1, table2, table3;
-- Add tables
alter publication sequin_publication add table table1, table2, table3;
-- Add all tables in a schema
alter publication sequin_publication add tables in schema my_schema;
-- Drop all tables in a schema
alter publication sequin_publication drop tables in schema my_schema;
```

### Deleting a Publication

You can delete a publication using the `DROP PUBLICATION` statement:

```sql
drop publication sequin_publication;
```

## Replication slots

[Replication slots](https://www.postgresql.org/docs/9.4/catalog-pg-replication-slots.html) ensure that PostgreSQL retains WAL (Write-Ahead Log) data needed by Sequin.

### Creating a Replication Slot

```sql
-- Create a logical replication slot that uses the built-in `pgoutput` plugin
SELECT pg_create_logical_replication_slot('sequin_slot', 'pgoutput');
```

### Deleting a Replication Slot

```sql
SELECT pg_drop_replication_slot('sequin_slot');
```

### Best practices

<Warning>
Create the [publication](#publications) **before** creating the replication slot. If you don't, the publication and slot combination may be invalid, and Sequin will fail to connect to your database.
</Warning>

**Monitor slot lag**
    Excessive lag in a replication slot can cause WAL buildup and disk space issues. Monitor lag with:

    ```sql
    select * from pg_replication_slots;
    ```

**Clean up unused slots**: Delete slots that are no longer in use to prevent WAL retention:

```sql
select pg_drop_replication_slot('sequin_slot');
```

## Replica identity

Sequin uses `REPLICA IDENTITY` to determine the old values of an updated row. These values are provided in the `changes` field in [messages](/reference/messages#param-changes).

### Changes

With `REPLICA IDENTITY` set to `FULL`, Sequin receives new and old values for all columns during updates. For columns that have changed values, Sequin includes the old values in the `changes` field.

### TOAST columns

PostgreSQL uses TOAST (The Oversized-Attribute Storage Technique) to store large column values. Here's how Sequin handles TOAST columns:

- TOAST columns are always included for INSERT operations
- For UPDATE operations:
  - Changed TOAST columns are included in rows and changes
  - Unchanged TOAST columns will appear as `"unchanged_toast"` unless `REPLICA IDENTITY` is set to `FULL`
  - If `REPLICA IDENTITY` is `FULL`, all TOAST columns are included regardless of changes
- For DELETE operations:
  - TOAST columns are included only if `REPLICA IDENTITY` is set to `FULL`

This behavior applies to both changes and rows in Sequin.

To set `REPLICA IDENTITY` to `FULL` for a table:

```sql
ALTER TABLE your_table REPLICA IDENTITY FULL;
```

## Using Sequin with a replica

Sequin supports connecting to a replica database, however in this case Sequin also needs to connect to the primary database.

The only operation that Sequin will perform on the primary database is to call the function `pg_logical_emit_message` to ensure proper WAL checkpointing.

The only permission required for this is `CONNECT` on the primary database.


## PostgreSQL 12 and 13

Sequin relies on the `pg_logical_emit_message` function for heartbeat messages and backfills. This function is included in Postgres 14 and later.

For Postgres 12 and 13, we support a table-based replacement: `public.sequin_logical_messages`.

You can create this table in your database with the following SQL:

```sql
CREATE TABLE IF NOT EXISTS public.sequin_logical_messages (
  id SERIAL PRIMARY KEY,
  slot_id TEXT NOT NULL,
  subject TEXT NOT NULL,
  content JSONB NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(slot_id, subject)
);

-- Grant permissions to Sequin
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE public.sequin_logical_messages TO sequin_user;
GRANT USAGE ON SEQUENCE sequin_logical_messages_id_seq TO sequin_user;
```

This table is used by Sequin to replace the `pg_logical_emit_message` function. It experiences very low write throughput and will not accumulate significant storage or IOPS.

This table **must be included in your publication** so that Sequin receives messages written to it. If you have created your publication with `ALL TABLES`, then this is done automatically. Otherwise, you can add the table to your publication with the following SQL:

```sql
ALTER PUBLICATION sequin_publication ADD TABLE public.sequin_logical_messages;
```

### Backfills

For Postgres 12 and 13, we do not support backfills, which rely heavily on the `pg_logical_emit_message` function.

If you require backfills, we recommend upgrading to Postgres 14 or later. If this is not an option, please [contact us](mailto:support@sequinstream.com) to discuss alternative approaches.

## Known issues

### Publication not recognized by replication slot

When a publication is created *after* the replication slot, Postgres may report that the publication does not exist. Sequin will surface this as an “Issue with publication” health check.

This is a [known Postgres issue](https://www.postgresql.org/message-id/18683-a98f79c0673be358%40postgresql.org).

**Fix**: drop and re-create the replication slot *after* the publication exists:

```sql
-- Drop the slot
SELECT pg_drop_replication_slot('sequin_slot');

-- Re-create the slot
SELECT pg_create_logical_replication_slot('sequin_slot', 'pgoutput');
```

**Prevention**: always create the publication first. If you need to change a publication later, alter it instead of dropping it:

```sql
-- Add or remove tables
ALTER PUBLICATION sequin_publication ADD TABLE new_table;
ALTER PUBLICATION sequin_publication DROP TABLE old_table;
```

See the full `ALTER PUBLICATION` documentation [here](https://www.postgresql.org/docs/current/sql-alterpublication.html).

## Monitoring

Sequin will run health checks against your database connection automatically. You can view the status of the connection at any time in your database's "Overview" page.
